

#ifndef _COMATH_H_
#define _COMATH_H_

#include "typedef.h"

typedef struct {
	uint8 number;
	uint8 index;
} ByteopSortResult;

typedef struct {
	uint16 number;
	uint8 index;
} WordopSortResult;

typedef struct {
	uint32 number;
	uint8 index;
} DwordopSortResult;

typedef struct
{
   uint32            current_crc;       /**< Current CRC-value */
   uint8*            crc_source_buffer;  /**< Pointer to source data */
   uint16            crc_byte_count;     /**< Number of bytes in source buffer */
} CoMathCrcParamType;

#define within(var, min, max) {		\
		if (var < min) {			\
			var = min;				\
		}							\
		else if (var > max) {		\
			var = max;				\
		}							\
		else {}						\
	}
#define calc_abs(data) (((data) >= 0) ? (data): (0-(data)))
#define calc_abs_error(data1, data2) (((data2) >= (data1))? ((data2) - (data1)) : ((data1) - (data2)))
#define calc_max(data1, data2) (((data1) >= (data2)) ? (data1): (data2))
#define calc_min(data1, data2) (((data1) <= (data2)) ? (data1): (data2))
#define calc_sign(data) (((data) >= 0) ? 1 : -1)

#define CRC8_START_VALUE        0xFFU
#define CRC8_XOR                0xFFU

/*
 * Get the 2 based logarithm for the specified data.
 * return value = floor(log2(data))
 * */
extern uint8 calc_floor_log2(uint16 data);

/*
 * Get the 2 based logarithm for the specified data.
 * return value = ceil(log2(data))
 * */
extern uint8 calc_ceil_log2(uint16 data);

uint8 calc_round_log2(uint16 data);

extern void   calc_coeff_and_bexp(uint16 data, uint16* coef, uint8* exp);
extern void   calc_limit_coeff_and_bexp(uint16 data, uint16 max_coeff, uint16* coef, uint8* exp);
extern uint16 calc_greast_common_divisor(uint16 a, uint16 b);
extern uint16 calc_least_common_multiple(uint16 a, uint16 b);
extern uint16 calc_round_div(uint16 a, uint16 b);

extern uint16 calc_period_lcm_16bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count);
#define wordop_calc_period_lcm(config, config_count, struct_type, struct_field) (calc_period_lcm_16bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count))

extern void sort_number_8bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, ByteopSortResult *sort_result);
extern void remove_sorted_number_by_index_8bit(ByteopSortResult *sorted_result, uint8 number_count, uint8 target_index);
#define byteop_sort_number(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_8bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern void sort_number_16bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, WordopSortResult *sort_result);
extern void remove_sorted_number_by_index_16bit(WordopSortResult *sorted_result, uint8 number_count, uint8 target_index);
#define wordop_sort_number(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_16bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern void sort_number_32bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, DwordopSortResult *sort_result);
extern void remove_sorted_number_by_index_32bit(DwordopSortResult *sort_result, uint8 number_count, uint8 target_index);
#define dwordop_sort_number(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_32bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern void sort_number_8bit_binary(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, ByteopSortResult *sort_result);
#define byteop_sort_number_binary(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_8bit_binary((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern void sort_number_16bit_binary(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, WordopSortResult *sort_result);
#define wordop_sort_number_binary(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_16bit_binary((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern void sort_number_32bit_binary(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, DwordopSortResult *sort_result);
#define dwordop_sort_number_binary(config, config_count, struct_type, struct_field, sort_result) do { \
		sort_number_32bit_binary((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, sort_result); \
} while(0)

extern uint8  find_config_index_from_sort_result_8bit(ByteopSortResult *sort_result, uint8 config_count, uint8 number);
extern uint8  find_config_index_from_sort_result_16bit(WordopSortResult *sort_result, uint8 config_count, uint16 number);
extern uint8  find_config_index_from_sort_result_32bit(DwordopSortResult *sort_result, uint8 config_count, uint32 number);

extern uint8 find_config_from_field_8bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, uint8 target_number);
#define byteop_find_config_from_field(config, config_count, struct_type, struct_field, target_number)   (find_config_from_field_8bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, target_number))

extern uint8 find_config_from_field_16bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, uint16 target_number);
#define wordop_find_config_from_field(config, config_count, struct_type, struct_field, target_number)   (find_config_from_field_16bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, target_number))

extern uint8 find_config_from_field_32bit(const uint8 *config, uint8 entry_size_in_byte, uint8 field_offset_in_byte, uint8 config_count, uint32 target_number);

extern void comath_init_crc32(CoMathCrcParamType *crc_param_pointer);
extern void comath_calc_crc32(CoMathCrcParamType *crc_param_pointer);

#define dwordop_find_config_from_field(config, config_count, struct_type, struct_field, target_number)   (find_config_from_field_32bit((const uint8*)(config), sizeof(struct_type), offsetof(struct_type, struct_field), config_count, target_number))

extern uint8 calc_crc8(const uint8* Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall );

#endif /* _COMATH_H_ */
